#include <iostream>
#include <string>
#include <ostream>
#include <map>
#include <math.h>
using namespace std;

template<typename Con>
void display(const Con & rhs){
    for(auto & ll : rhs){
        cout << ll.first<<"  string = " << ll.second << endl;
    } 
}

class Point{
public:
    Point(int x, int y)
        :_x(x)
         ,_y(y)
    {    }

    // 获得x
    int getX() const{
        return _x;
    }
    // 获得y
    int getY() const{
        return _y;
    }
    // 获得距离比较
    double getDistance() const{
        return hypot(_x, _y);
    }
private:
    int _x;
    int _y;
};


// 使用自定义类函数模版
struct Compare{
    bool operator()(const Point & ihs, const Point & rhs) const{
        cout << "---Compare---" << endl;
        if(ihs.getDistance() < rhs.getDistance()){// 距离小于直接返回true
            return true; 
        }else if(ihs.getDistance() == rhs.getDistance()){ // 距离相等的情况下
            if(ihs.getX() < rhs.getX()){    // ihs._x大返回true
                return true;
            }else if(ihs.getX() == rhs.getX()){ // 判断 x 是不是一样
                if(ihs.getY() < rhs.getY()){    // 判断 y 
                    return true;            
                }else{                      
                    return false;
                }
            }else{
                return false;
            }
        }else{
            return false;
        }

    }
};

//  输出流的重载
ostream & operator<<(ostream & os, const Point & rhs){

    os << "Point(" 
        << rhs.getX() << ", " 
        << rhs.getY() << ")" ;
    return os;
}
// 运算符的重载
bool operator<(const Point & ihs, const Point & rhs){
    cout << "---operator<----" << endl;

    if(ihs.getDistance() < rhs.getDistance()){// 距离小于直接返回true
        return true; 
    }else if(ihs.getDistance() == rhs.getDistance()){ // 距离相等的情况下
        if(ihs.getX() < rhs.getX()){    // ihs._x大返回true
            return true;
        }else if(ihs.getX() == rhs.getX()){ // 判断 x 是不是一样
            if(ihs.getY() < rhs.getY()){    // 判断 y 
                return true;    
            }else{                  
                return false;
            }
        }else{
            return false;
        }
    }else{
        return false;
    }
}

// 命名空间
// 模版特化
namespace std{
template<>
    class less<Point>{
    public:
        bool operator()(const Point & ihs, const Point & rhs) const{
            cout << "namespace template<>" << endl;
            if(ihs.getDistance() < rhs.getDistance()){// 距离小于直接返回true
                return true;
            }else if(ihs.getDistance() == rhs.getDistance()){ // 距离相等的情况下
                if(ihs.getX() < rhs.getX()){    // ihs._x大返回true
                    return true;
                }else if(ihs.getX() == rhs.getX()){ // 判断 x 是不是一样
                    if(ihs.getY() < rhs.getY()){    // 判断 y 
                        return true;
                    }else{                  
                        return false;
                    }
                }else{
                    return false;
                }
            }else{
                return false;
            }

        }
    };
};
void test(){
    // 谁写在前面谁就是Key，Key是第一个元素
    // 跟set之前出现的原因一样，map的默认的比较函数中没有对Point的比较方法
    // 要自己写，有三种方法，跟set一样的
    // 1. 运算符重载
    // 2. 命名空间函数 模版特殊化
    // 3. 自定义函数模版（排序规则）
    //map<Point,string,Compare> mp = {
    map<Point,string> mp = {
        {Point(1,2),"xiaowang"},
        {Point(-1,-2),"liang"},
        {Point(1,-2),"zhao"},
        {Point(3,4),"nihao"},
        {Point(1,2),"wangdao"}
    };

    display(mp);
}

int main(int atgc, char * argv[])
{
    test();
    return 0;
}

